/// string study
/*
字符串类型
    `str` 是一个字符串 slice 类型，它是一个不可变的引用，通常以 `&str` 的形式出现。这意味着，`str` 对象指向的字符串数据在内存中是固定的，并且不能被更改。
    `String` 是一个堆分配的可变字符串类型，它通常以 `String` 的形式出现。这意味着，`String` 对象中存储的字符串数据可以随时在堆上进行修改。
    1/`&str` 是指向 UTF-8 编码字符串切片的引用。它通常被用于函数的参数和返回值。
    2/String` 类型是一个可变的、拥有自己的内存的字符串类型。可以使用 `new` 函数来创建一个新的空字符串，也可以使用 `from` 函数从一个 `&str` 类型的引用创建一个 `String` 类型的实例。
 */
pub fn str_push() {
    let mut s = String::new();
    s.push_str("hello");
    s.push_str("str_test");
    println!("{}", s);
}


// 字符串拼接：`+` 运算符或 `format!` 宏来将两个字符串拼接起来
pub fn str_join() {
    // 使用 `+` 运算符时，左操作数必须是 `String` 类型，右操作数可以是 `&str` 或 `String` 类型的引用
    let hello = "Hello ".to_string();
    let world = "world!";
    let hello_world = hello + world;
    println!("{}", hello_world);
    // method 2
    let hello2 = "Hello ".to_string();
    let world2 = "world!".to_string();
    let hello_world2 = hello2 + &world2;
    println!("{}", hello_world2);

    //使用 `format!` 宏时，可以将多个值格式化成一个字符串。
    let s4 = format!("{} {}", "hello", "world");
    println!("{}", s4);
}

//字符串切割：`split` 方法将一个字符串切割成多个子串
pub fn str_split(){
    let s1 = String::from("hello,world");
    let tokens: Vec<&str> = s1.split(",").collect();

    for token in tokens {
        println!("{}", token);
    }
}

// 字符串替换：`replace` 方法将一个字符串中的某个子串替换为另一个子串
pub fn str_replace(){
    let s1 = String::from("hello,world");
    let s2 = s1.replace(",", "----");

    println!("{}", s2); // hello world
}
// 字符串查找 :
//`find` 方法在一个字符串中查找某个子串的位置。如果找到了该子串，则返回它在字符串中的起始索引；
//否则返回 `None`
pub fn str_find(){
    let s1 = String::from("hello,world");
    let index = s1.find(",");

    match index {
        Some(i) => println!("found at index {}", i),
        None => println!("not found"),
    }
}

// This function is for string
/*
由于 Rust 的字符串类型是基于 UTF-8 编码的，因此每个字符可能占用不同的字节数。
为了正确地遍历一个字符串中的字符，我们需要使用迭代器和相关的方法。
 */
pub fn str_for() {
    let hachiko = "忠犬ハチ公";

   // 使用 chars 方法创建一个字符迭代器
    for c in hachiko.chars() {
        print!("{}, ", c);//忠, 犬, ハ, チ, 公,
    }
    print!("\n");
    // get index
    let dog = hachiko.chars().nth(1);
    println!("{:?}", dog);//Some('犬')

    /*
   除了 `chars` 方法外，Rust 还提供了其他一些常用的方法来处理字符串：
   - `bytes()`：返回一个字节迭代器，用于遍历字符串中的每个字节。
   - `char_indices()`：返回一个元组迭代器，用于遍历字符串中每个字符的索引和字符本身。
   - `split_whitespace()`：返回一个字符串切割迭代器，用于按照空格将字符串分隔成多个子串。
   - `lines()`：返回一个字符串切割迭代器，用于将字符串按照行分隔成多个子串。
    */
    let s = String::from("hello, world世界");

    // 使用 bytes 方法遍历每个字节
    for b in s.bytes() {
        println!("{}", b);
    }

    // 使用 char_indices 方法遍历每个字符和它的索引
    for (i, c) in s.char_indices() {
        println!("{}, {}", i, c);
    }

    // 使用 split_whitespace 方法切割字符串并遍历子串
    for word in s.split_whitespace() {
        println!("{}", word);
    }

    // 使用 lines 方法切割字符串并遍历行
    for line in s.lines() {
        println!("{}", line);
    }
}